package fiuba.algo3;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class Policia {
	static final int TIEMPO_TOTAL = 134;		// horas totales desde lunes 7hs a domingo 17 hs
	static final int MINIMO_HORAS_A_PERMANECER_DESPIERTO = 18;
	static final int HORAS_EMITIR_ORDEN_DE_ARRESTO = 3;
	static final int FIN_DEL_TIEMPO = 0;
	static final int HORAS_DE_SUENIO = 8;
	private int arrestos;
	private Ciudad ciudadActual;
	private Grado grado;
	private int tiempoRestante = TIEMPO_TOTAL;
	private OrdenDeArresto ordenDeArresto = new OrdenDeArresto();
	private int despertoPorUltimaVez;
	private String nombre;
	
	public Policia() {
		this.arrestos = 0;
		this.grado = new Novato();
		this.despertoPorUltimaVez = TIEMPO_TOTAL;
	}
	
	public Node serializar(Document doc){
		Element elementPolicia = doc.createElement("Policia");
		elementPolicia.setAttribute("arrestos", Integer.toString(this.arrestos));
		elementPolicia.appendChild(this.ciudadActual.serializar(doc));
		elementPolicia.appendChild(this.grado.serializar(doc));
		elementPolicia.setAttribute("tiempoRestante", Integer.toString(this.tiempoRestante));
		elementPolicia.appendChild(this.ordenDeArresto.serializar(doc));
		elementPolicia.setAttribute("despertoPorUltimaVez", Integer.toString(this.despertoPorUltimaVez));
		elementPolicia.setAttribute("nombre", this.nombre);
		return elementPolicia;
	}
	
	public static Policia hidratar(Node elementoPolicia){
		Policia nuevoPolicia = new Policia();
		nuevoPolicia.arrestos = Integer.parseInt( ((Element)elementoPolicia).getAttribute("arrestos") );
		nuevoPolicia.ciudadActual = Ciudad.hidratar( ((Element) elementoPolicia).getElementsByTagName("Ciudad").item(0) );
		nuevoPolicia.grado = Grado.hidratar( ((Element) elementoPolicia).getElementsByTagName("Grado").item(0) );
		nuevoPolicia.tiempoRestante = Integer.parseInt( ((Element)elementoPolicia).getAttribute("tiempoRestante") );
		nuevoPolicia.ordenDeArresto = OrdenDeArresto.hidratar( ((Element) elementoPolicia).getElementsByTagName("OrdenDeArresto").item(0) );
		nuevoPolicia.despertoPorUltimaVez = Integer.parseInt( ((Element)elementoPolicia).getAttribute("despertoPorUltimaVez") );
		nuevoPolicia.nombre = ((Element)elementoPolicia).getAttribute("nombre");
		return nuevoPolicia;
	}
	
	// SETTERS
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	
	public void setCiudad(Ciudad unaCiudad) {
		this.ciudadActual = unaCiudad;
	}
	// FIN SETTERS

	// GETTERS
	public int getTiempoRestante() {
		return this.tiempoRestante;
	}
	
	public int getArrestos() {
		return this.arrestos;
	}
	
	public Ciudad getCiudadActual() {
		return this.ciudadActual;
	}
	
	public OrdenDeArresto getOrdenDeArresto() {
		return this.ordenDeArresto;
	}
	
	public Grado getGrado() {
		return this.grado;
	}
	
	public String getNombre() {
		return this.nombre;
	}
	// FIN GETTERS
	
	public void viajarA(Ciudad ciudadDestino) {
		int distancia = this.ciudadActual.obtenerDistanciaHasta(ciudadDestino);
		this.disminuirTiempo(calcularHorasDeViaje(distancia));
		setCiudad(ciudadDestino);
		verificarSiDebeDormir();
	}
	
	private int calcularHorasDeViaje (int distancia) {
		int horas = (int) (distancia / this.grado.getVelocidad());
		return horas;
	}
	
	public Pista recibirPista(Edificio unEdificio){
		Pista pista = this.grado.recibirPista(unEdificio);
		return pista;
	}
	
	public Caso recibirCaso() {
		this.tiempoRestante = TIEMPO_TOTAL;
		Caso caso = this.grado.recibirCaso();
		this.ciudadActual = caso.getCiudadInicial();
		this.ordenDeArresto = new OrdenDeArresto();
		return caso;
	}
	
	public void efectuarArresto() {
		this.arrestos = this.arrestos + 1;
		switch (this.arrestos){
		case 5:	this.ascenderDeGrado(); break;
		case 10: this.ascenderDeGrado(); break;
		case 20: this.ascenderDeGrado(); break;
		}
	}
	
	private void ascenderDeGrado() {
		this.grado = this.grado.ascenderDeGrado();
	}
	
	// METODOS RELACIONADOS CON ORDEN DE ARRESTO
	public void ingresarSexoSospechoso(String sexo) {
		this.ordenDeArresto.setSexo(sexo);		
	}
	
	public void ingresarHobbySospechoso(String hobby) {
		this.ordenDeArresto.setHobby(hobby);		
	}
	
	public void ingresarCabelloSospechoso(String cabello) {
		this.ordenDeArresto.setCabello(cabello);		
	}
	
	public void ingresarSeniaSospechoso(String senia) {
		this.ordenDeArresto.setSenia(senia);		
	}
	
	public void ingresarAutoSospechoso(String auto) {
		this.ordenDeArresto.setAuto(auto);		
	}
	
	public boolean tieneOrdenDeArresto() {
		return this.ordenDeArresto.estaAprobada();
	}
	// FIN
	
	// METODOS QUE RESTAN TIEMPO
	public void visitarEdificio(Edificio unEdificio) {
		unEdificio.visitado();
		this.disminuirTiempo(unEdificio.getVecesVisitado());
		verificarSiDebeDormir();	
	}

	public void recibirHerida(Arma arma) {
		this.disminuirTiempo(arma.getHorasDeCuracion());
		verificarSiDebeDormir();
	}
	
	public boolean emitirOrdenDeArresto() {
		this.disminuirTiempo(HORAS_EMITIR_ORDEN_DE_ARRESTO);
		boolean resultado = this.ordenDeArresto.verificarOrdenDeArresto();
		verificarSiDebeDormir();
		return resultado;
	}
	// FIN
	
	// METODOS RELACIONADOS CON EL TIEMPO
	public void verificarSiDebeDormir() {
		if (this.despertoPorUltimaVez - this.tiempoRestante >= MINIMO_HORAS_A_PERMANECER_DESPIERTO){
			this.disminuirTiempo(HORAS_DE_SUENIO);
			this.despertoPorUltimaVez = this.tiempoRestante;
			// se puede sacar PERO ME GUSTA QUE DIGA QUE DUERME!
			System.out.println("*** ... Policia durmiendo ...");
		}
	}
	
	public boolean tiempoCumplido() {
		if ( this.tiempoRestante > FIN_DEL_TIEMPO){
			return false;
		}
		return true;
	}
	
	private void disminuirTiempo(int horas) {
		this.tiempoRestante = this.tiempoRestante - horas;
	}
	// FIN
	
}
